/**
 * <p>文件名:		JMXManager.java</p>
 * <p>版权:		Caits</p>
 * <p>公司:		Caits</p>
 * @author 		宋晓达 ٩(·̮̃·̃)۶ (songxiaoda@ctfo.com)
 */

package com.caits.lbs.framework.services.jmx;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.JMException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBean;
import javax.management.modelmbean.ModelMBeanInfo;

import org.apache.log4j.Logger;
import org.springframework.jmx.export.MBeanExportException;
import org.springframework.jmx.export.SpringModelMBean;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.assembler.MBeanInfoAssembler;
import org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler;
import org.springframework.util.Assert;

import com.caits.lbs.bean.dbmodel.ETBase;
import com.caits.lbs.framework.log.CommonLogFactory;

/**
 * <p>
 * JMXManager
 * </p>
 * <p>
 * spring提供的JMX管理基本办法, 提供通用可配置JMX 使用方法，
 * <OL>
 * <Li>在exporter中增加map的实例id</LI>
 * <LI>在自己的代码中调用JMXManager.add(obj)方法</LI>
 * </OL>
 * </p>
 * 
 * @author 周华彬(zhouhuabin@ctfo.com, zhou_hua_bin@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">版本号</th>
 *          <th width="100px">动作</th>
 *          <th width="100px">修改人</th>
 *          <th width="100px">修改时间</th>
 *          </tr>
 *          <!-- 以 Table 方式书写修改历史 -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td>创建类</td>
 *          <td>zhb</td>
 *          <td>2011-3-18 下午04:44:55</td>
 *          </tr>
 *          <tr>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          </tr>
 *          </table>
 */
@ManagedResource(objectName = "bean:name=JMXManager", description = "My Managed Bean", log = true, logFile = "JMXManager.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200, persistLocation = "foo", persistName = "bar")
public class JMXManager {

	private static final String MR_TYPE_OBJECT_REFERENCE = "ObjectReference";

	/** 远程管理的对象列表 */
	private List<Object> values = Collections
			.synchronizedList(new LinkedList<Object>());

	/** spring提供jmx暴露器 */
	private org.springframework.jmx.export.MBeanExporter mExporter = null;

	/** Stores the MBeanInfoAssembler to use for this exporter */
	private MBeanInfoAssembler assembler = new SimpleReflectiveMBeanInfoAssembler();

	/** 日志类 */
	private Logger log = CommonLogFactory.getLog();

	/**
	 * 构造器
	 */
	public JMXManager() {
		log.info("JMXManager实例开始初始化.hashCode="+hashCode());
		Assert.isNull(instance, "JMXManager实例已经初始化.");
		instance = this;
	}

	/** 单一实例 */
	private static JMXManager instance = null;

	/**
	 * 获取列表
	 * 
	 * @return
	 */
	@ManagedOperation(description = "get specied object", currencyTimeLimit = 1)
	@ManagedOperationParameters({ @ManagedOperationParameter(name = "index", description = "The specied position") })
	public Object getObject(int index) {
		if (index >= 0 && index < values.size())
			return values.get(index);
		else
			return "index larger than list.size";
	}

	/**
	 * 注册要管理的对象
	 * 
	 * @param o
	 * @param name
	 */
	public void registMBean(Object o, String name) {

		try {
			Assert.notNull(mExporter, "注册器未正确配置，请检查jmx配置再试.");
			mExporter.getServer().registerMBean(adaptMBeanIfPossible(o, name),
					new ObjectName(name));
		} catch (InstanceAlreadyExistsException e) {
			log.error("注册MBean异常", e);
		} catch (MBeanRegistrationException e) {
			log.error("注册MBean异常", e);
		} catch (NotCompliantMBeanException e) {
			log.error("注册MBean异常", e);
		} catch (MalformedObjectNameException e) {
			log.error("注册MBean异常", e);
		} catch (NullPointerException e) {
			log.error("注册MBean异常", e);
		} catch (JMException e) {
			log.error("注册MBean异常", e);
		}catch(Exception e){
			log.error("注册MBean异常", e);
		}

	}
	
	/**
	 * 根据名称注销对象 
	 * @param name
	 */
	public void unregistMBean(String name) {
		try {
			Assert.notNull(mExporter, "注册器未正确配置，请检查jmx配置再试.");
			mExporter.getServer().unregisterMBean(new ObjectName(name));
		} catch (MBeanRegistrationException e) {
			log.error("注销MBean异常", e);
		} catch (MalformedObjectNameException e) {
			log.error("注销MBean异常", e);
		} catch (NullPointerException e) {
			log.error("注销MBean异常", e);
		} catch (JMException e) {
			log.error("注销MBean异常", e);
		}catch(Exception e){
			log.error("注销MBean异常", e);
		}

	}

	/**
	 * 增加要管理的对象
	 * 
	 * @param obj
	 */
	@ManagedOperation(description = "Add one to MBean")
	@ManagedOperationParameters({ @ManagedOperationParameter(name = "obj", description = "The first obj") })
	public void addObject(Object obj) {
		if (obj != null&&mExporter!=null) {
			values.add(obj);
			registMBean(obj, obj.getClass().getPackage().getName() + ":type="
					+ obj.getClass().getSimpleName()+obj.hashCode());
		}
	}

	/**
	 * 从管理器中注销对象 
	 * @param obj
	 */
	public void removeObject(Object obj) {
		if (obj != null) {
			values.remove(obj);
			unregistMBean( obj.getClass().getPackage().getName() + ":type="
					+ obj.getClass().getSimpleName()+obj.hashCode());
		}
	}
	/**
	 * 增加一个测试对象
	 */
	public void addTestObject() {
		addObject(new ETBase());
	}

	/**
	 * 获得单一实例
	 * 
	 * @return
	 */
	public static JMXManager getInstance() {
		return instance;
	}

	/**
	 * 获取变量<code>mExporter</code>的值
	 * 
	 * @return 返回的数据类型是<code>org.springframework.jmx.export.MBeanExporter</code>
	 */
	public org.springframework.jmx.export.MBeanExporter getmExporter() {
		return mExporter;
	}

	/**
	 * 设置变量<code> mExporter</code> 的值
	 * 
	 * @param mExporter
	 *            <code>mExporter</code> 参数类型是
	 *            <code>org.springframework.jmx.export.MBeanExporter</code>
	 */
	public void setmExporter(
			org.springframework.jmx.export.MBeanExporter mExporter) {
		this.mExporter = mExporter;

	}

	/**
	 * 设置所有实例的日志级别 
	 * @param level
	 * @return
	 */
	public String setAllLogLevel(int level) {
		String ret = null;
		for(Object obj:values){
			if(obj instanceof ILogSetable){
				ILogSetable bean=(ILogSetable)obj;
				ret = bean.setLevel(level);
			}
		}
		return ret;
	}

	/**
	 * 构建
	 * 
	 * @param bean
	 * @param beanKey
	 * @return
	 * @throws JMException
	 */
	protected DynamicMBean adaptMBeanIfPossible(Object bean, String beanKey)
			throws JMException {
		try {
			ModelMBean mbean = createModelMBean();
			ModelMBeanInfo info = assembler.getMBeanInfo(bean, beanKey);
			mbean.setModelMBeanInfo(info);
			mbean.setManagedResource(bean, MR_TYPE_OBJECT_REFERENCE);
			return mbean;
		} catch (Exception ex) {
			throw new MBeanExportException(
					"Could not create ModelMBean for managed resource [" + bean
							+ "] with key '" + beanKey + "'", ex);
		}
	}

	/**
	 * 创建ModelMBean
	 * 
	 * @return
	 * @throws MBeanException
	 */
	private ModelMBean createModelMBean() throws MBeanException {
		return new SpringModelMBean();
		//return  new RequiredModelMBean();
	}

	/**
	 * 集合的大小 
	 * @return
	 */
	public int size() {
		return values.size();
	}
}
